package com.sz.virtualbank.web.controller.transaction;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.sz.virtualbank.common.annotation.LoginRequired;
import com.sz.virtualbank.common.constant.CommonConstants;
import com.sz.virtualbank.common.result.CommonResponse;
import com.sz.virtualbank.common.utils.CheckUtil;
import com.sz.virtualbank.dao.entity.TradeRecord;
import com.sz.virtualbank.dao.entity.User;
import com.sz.virtualbank.service.transaction.TransactionService;
import com.sz.virtualbank.service.user.UserService;
import com.sz.virtualbank.web.vo.transaction.RechargeReqVO;
import com.sz.virtualbank.web.vo.transaction.TradeRecordVO;
import com.sz.virtualbank.web.vo.transaction.TransferReqVO;
import com.sz.virtualbank.web.vo.transaction.WithdrawReqVO;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;

/**
 * 交易控制器
 *
 * @author Claude
 */
@Slf4j
@RestController
@RequestMapping("/api/transaction")
@Api(tags = "交易接口")
public class TransactionController {

    @Autowired
    private TransactionService transactionService;

    @Autowired
    private UserService userService;

    @PostMapping("/recharge")
    @LoginRequired
    @ApiOperation("账户充值")
    public CommonResponse<TradeRecordVO> recharge(@RequestBody @Valid RechargeReqVO rechargeReq,
                                                  HttpServletRequest request) {
        // 获取当前用户
        User currentUser = getCurrentUser(request);

        // 调用充值服务
        TradeRecord tradeRecord = transactionService.recharge(
                currentUser.getId(),
                rechargeReq.getAmount(),
                rechargeReq.getChannel()
        );

        // 转换为VO返回
        TradeRecordVO tradeRecordVO = convertToTradeRecordVO(tradeRecord);

        return CommonResponse.buildSuccess("充值成功", tradeRecordVO);
    }

    @PostMapping("/withdraw")
    @LoginRequired
    @ApiOperation("账户提现")
    public CommonResponse<TradeRecordVO> withdraw(@RequestBody @Valid WithdrawReqVO withdrawReq,
                                                  HttpServletRequest request) {
        // 获取当前用户
        User currentUser = getCurrentUser(request);

        // 验证支付密码，实际项目中应该是加密的密码
        // TODO: 验证支付密码逻辑
        CheckUtil.Biz.INSTANCE.isTrue(StringUtils.isNotBlank(withdrawReq.getPayPassword()), "支付密码不能为空");

        // 调用提现服务
        TradeRecord tradeRecord = transactionService.withdraw(
                currentUser.getId(),
                withdrawReq.getAmount(),
                withdrawReq.getChannel()
        );

        // 转换为VO返回
        TradeRecordVO tradeRecordVO = convertToTradeRecordVO(tradeRecord);

        return CommonResponse.buildSuccess("提现申请已提交", tradeRecordVO);
    }

    @PostMapping("/transfer")
    @LoginRequired
    @ApiOperation("转账")
    public CommonResponse<TradeRecordVO> transfer(@RequestBody @Valid TransferReqVO transferReq,
                                                  HttpServletRequest request) {
        // 获取当前用户
        User currentUser = getCurrentUser(request);

        // 验证支付密码，实际项目中应该是加密的密码
        // TODO: 验证支付密码逻辑
        CheckUtil.Biz.INSTANCE.isTrue(StringUtils.isNotBlank(transferReq.getPayPassword()), "支付密码不能为空");

        // 调用转账服务
        TradeRecord tradeRecord = transactionService.transfer(
                currentUser.getId(),
                transferReq.getTargetAccount(),
                transferReq.getAmount(),
                transferReq.getRemark()
        );

        // 转换为VO返回
        TradeRecordVO tradeRecordVO = convertToTradeRecordVO(tradeRecord);

        return CommonResponse.buildSuccess("转账成功", tradeRecordVO);
    }

    @GetMapping("/list")
    @LoginRequired
    @ApiOperation("查询交易记录列表")
    public CommonResponse<List<TradeRecordVO>> listTradeRecords(
            @RequestParam(required = false) @ApiParam("交易类型") Integer tradeType,
            @RequestParam(required = false) @ApiParam("开始时间") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @RequestParam(required = false) @ApiParam("结束时间") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
            @RequestParam(required = false, defaultValue = "1") @ApiParam("页码") Integer pageNum,
            @RequestParam(required = false, defaultValue = "10") @ApiParam("每页记录数") Integer pageSize,
            HttpServletRequest request) {

        // 获取当前用户
        User currentUser = getCurrentUser(request);

        // 查询交易记录
        List<TradeRecord> tradeRecords;

        if (tradeType != null) {
            // 根据交易类型查询
            tradeRecords = transactionService.listTradeRecordsByType(currentUser.getId(), tradeType, pageNum, pageSize);
        } else if (startTime != null && endTime != null) {
            // 根据时间范围查询
            tradeRecords = transactionService.listTradeRecordsByDateRange(currentUser.getId(), startTime, endTime, pageNum, pageSize);
        } else {
            // 查询所有
            tradeRecords = transactionService.listTradeRecords(currentUser.getId(), pageNum, pageSize);
        }

        // 转换为VO列表
        List<TradeRecordVO> tradeRecordVOs = new ArrayList<>();
        for (TradeRecord tradeRecord : tradeRecords) {
            tradeRecordVOs.add(convertToTradeRecordVO(tradeRecord));
        }

        return CommonResponse.buildSuccess(tradeRecordVOs);
    }

    @GetMapping("/detail/{tradeNo}")
    @LoginRequired
    @ApiOperation("查询交易详情")
    public CommonResponse<TradeRecordVO> getTradeDetail(@PathVariable @ApiParam("交易流水号") String tradeNo,
                                                        HttpServletRequest request) {
        // 获取当前用户
        User currentUser = getCurrentUser(request);

        // 查询交易详情
        TradeRecord tradeRecord = transactionService.getTradeDetail(tradeNo);

        // 检查是否是当前用户的交易
        CheckUtil.Biz.INSTANCE.isTrue(tradeRecord.getUserId().equals(currentUser.getId()), "无权查看该交易记录");

        // 转换为VO返回
        TradeRecordVO tradeRecordVO = convertToTradeRecordVO(tradeRecord);

        return CommonResponse.buildSuccess(tradeRecordVO);
    }

    /**
     * 获取当前用户
     *
     * @param request HTTP请求
     * @return 当前用户
     */
    private User getCurrentUser(HttpServletRequest request) {
        // 从Cookie中获取Token
        String token = getTokenFromCookie(request);
        CheckUtil.Biz.INSTANCE.notEmpty(token, "未登录或登录已过期");

        // 获取当前用户
        return userService.getCurrentUser(token);
    }

    /**
     * 从Cookie中获取Token
     *
     * @param request HTTP请求
     * @return Token
     */
    private String getTokenFromCookie(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (CommonConstants.COOKIE_NAME.equals(cookie.getName())) {
                    return cookie.getValue();
                }
            }
        }

        return null;
    }

    /**
     * 转换为交易记录视图对象
     *
     * @param tradeRecord 交易记录实体
     * @return 交易记录视图对象
     */
    private TradeRecordVO convertToTradeRecordVO(TradeRecord tradeRecord) {
        if (tradeRecord == null) {
            return null;
        }

        TradeRecordVO tradeRecordVO = new TradeRecordVO();
        BeanUtils.copyProperties(tradeRecord, tradeRecordVO);

        // 设置交易类型名称
        if (tradeRecord.getTradeType() != null) {
            switch (tradeRecord.getTradeType()) {
                case 1:
                    tradeRecordVO.setTradeTypeName("充值");
                    break;
                case 2:
                    tradeRecordVO.setTradeTypeName("提现");
                    break;
                case 3:
                    tradeRecordVO.setTradeTypeName("转账");
                    break;
                case 4:
                    tradeRecordVO.setTradeTypeName("支付");
                    break;
                case 5:
                    tradeRecordVO.setTradeTypeName("退款");
                    break;
                default:
                    tradeRecordVO.setTradeTypeName("其他");
                    break;
            }
        }

        // 设置交易状态名称
        if (tradeRecord.getStatus() != null) {
            switch (tradeRecord.getStatus()) {
                case 0:
                    tradeRecordVO.setStatusName("处理中");
                    break;
                case 1:
                    tradeRecordVO.setStatusName("成功");
                    break;
                case 2:
                    tradeRecordVO.setStatusName("失败");
                    break;
                default:
                    tradeRecordVO.setStatusName("未知");
                    break;
            }
        }

        // 设置交易渠道名称
        if (StringUtils.isNotBlank(tradeRecord.getChannel())) {
            switch (tradeRecord.getChannel()) {
                case "ALIPAY":
                    tradeRecordVO.setChannelName("支付宝");
                    break;
                case "WECHAT":
                    tradeRecordVO.setChannelName("微信");
                    break;
                case "BANK_CARD":
                    tradeRecordVO.setChannelName("银行卡");
                    break;
                case "INTERNAL":
                    tradeRecordVO.setChannelName("内部");
                    break;
                default:
                    tradeRecordVO.setChannelName(tradeRecord.getChannel());
                    break;
            }
        }

        return tradeRecordVO;
    }
}
